package com.tqz.dt.proxy;

import com.tqz.dt.interceptors.GlobalTransactionalInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;

/**
 * <p>AOP拦截调用链
 *
 * @author tianqingzhao
 * @since 2021/7/7 15:35
 */
public class AopAdviceChainInvocation implements MethodInvocation {

    /**
     * 代理对象
     */
    private Object proxy;

    /**
     * 目标对象
     */
    private Object target;

    /**
     * 拦截的方法
     */
    private Method method;

    /**
     * 参数
     */
    private Object[] args;

    /**
     * 所有的通知
     */
    private List<Object> advices;

    /**
     * 责任链执行记录索引号
     */
    private int currentInterceptorIndex = -1;

    public AopAdviceChainInvocation(Object proxy, Object target, Method method, Object[] args, List<Object> advices) {
        super();
        this.proxy = proxy;
        this.target = target;
        this.method = method;
        this.args = args;
        this.advices = advices;
    }

    @Override
    public Object proceed() throws Throwable {
        // 调用目标对象
        if (this.currentInterceptorIndex == this.advices.size() - 1) {
            return method.invoke(target, args);
        }

        Object interceptorOrInterceptionAdvice = this.advices.get(++this.currentInterceptorIndex);
        return ((GlobalTransactionalInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }

    @Override
    public Object getThis() {
        return target;
    }

    @Override
    public AccessibleObject getStaticPart() {
        return null;
    }

    @Override
    public Method getMethod() {
        return this.method;
    }

    @Override
    public Object[] getArguments() {
        return args;
    }
}
